package com.qqtech.qquan.sys.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.common.base.Splitter;
import com.qqtech.core.frame.dao.BaseDao;
import com.qqtech.core.frame.service.BaseServiceImpl;
import com.qqtech.qquan.sys.dao.SysFunctionDao;
import com.qqtech.qquan.sys.dao.SysMenuDao;
import com.qqtech.qquan.sys.dao.SysRoleDao;
import com.qqtech.qquan.sys.dao.SysRoleFunctionDao;
import com.qqtech.qquan.sys.dao.SysRoleMenuDao;
import com.qqtech.qquan.sys.dao.SysRoleUserDao;
import com.qqtech.qquan.sys.enums.SysConst;
import com.qqtech.qquan.sys.enums.SysMenuStatusDictEnum;
import com.qqtech.qquan.sys.enums.SysMenuTypeDictEnum;
import com.qqtech.qquan.sys.enums.SysRoleStatusDictEnum;
import com.qqtech.qquan.sys.model.SysFunction;
import com.qqtech.qquan.sys.model.SysFunctionQuery;
import com.qqtech.qquan.sys.model.SysFunctionVo;
import com.qqtech.qquan.sys.model.SysMenu;
import com.qqtech.qquan.sys.model.SysMenuVo;
import com.qqtech.qquan.sys.model.SysRole;
import com.qqtech.qquan.sys.model.SysRoleFunction;
import com.qqtech.qquan.sys.model.SysRoleMenu;
import com.qqtech.qquan.sys.model.SysRoleQuery;
import com.qqtech.qquan.sys.model.SysRoleUser;
import com.qqtech.qquan.sys.model.SysRoleVo;
import com.qqtech.qquan.user.model.UserAdmin;
import com.qqtech.qquan.user.model.UserAdminVo;

@Service
public class SysRoleServiceImpl extends BaseServiceImpl<SysRole>
		implements SysRoleService {
	public static final Logger log = LoggerFactory.getLogger(SysRoleServiceImpl.class);
	
	@Resource
	private SysRoleDao sysRoleDao;
	@Resource
	private SysRoleFunctionDao sysRoleFunctionDao;
	@Resource
	private SysFunctionDao sysFunctionDao;
	@Resource
	private SysMenuDao sysMenuDao;
	@Resource
	private SysRoleMenuDao sysRoleMenuDao;
	@Resource
	private SysRoleUserDao sysRoleUserDao;

	@Override
	protected BaseDao<SysRole> getBaseDao() {
		return sysRoleDao;
	}
	
	@Override
	public SysRoleVo getByName(java.lang.String name) {
		return sysRoleDao.getByName(name);
	}

	@Override
	public int handleSaveRole(SysRoleVo sysRole) {
		Integer roleId = sysRoleDao.insert(sysRole);
		if (roleId != null && StringUtils.isNotBlank(sysRole.getFunctionIds())) {
			Iterator<String> it = Splitter.on(",").trimResults().split(sysRole.getFunctionIds()).iterator();
            while(it.hasNext()) {  
            	// 保存角色功能
            	Integer functionId = Integer.valueOf(it.next());
            	SysRoleFunction rf = new SysRoleFunction();
            	rf.setFunctionId(functionId);
            	rf.setRoleId(roleId);
            	sysRoleFunctionDao.insert(rf);
            }
		}
		return 0;
	}

	@Override
	public int handleUpdateRole(SysRoleVo sysRole) {
		int value = sysRoleDao.updateById(sysRole);
		if (value > 0) {
			if (StringUtils.isNotBlank(sysRole.getFunctionIds())) {
				Iterator<String> it = Splitter.on(",").trimResults().split(sysRole.getFunctionIds()).iterator();
	            while(it.hasNext()) { 
	            	// 保存角色功能
	            	Integer functionId = Integer.valueOf(it.next());
	            	SysRoleFunction rf = new SysRoleFunction();
	            	rf.setFunctionId(functionId);
	            	rf.setRoleId(sysRole.getId());
	            	if (!checkHasRoleFunc(rf)) {
	            		sysRoleFunctionDao.insert(rf);
	            	}
	            }
			}
			if (StringUtils.isNotBlank(sysRole.getUncheckdFunctionId())) {
				Iterator<String> it2 = Splitter.on(",").trimResults().split(sysRole.getUncheckdFunctionId()).iterator();
				 while(it2.hasNext()) {
					 SysRoleFunction rf = new SysRoleFunction();
					 Integer functionId = Integer.valueOf(it2.next());
					 rf.setFunctionId(functionId);
					 rf.setRoleId(sysRole.getId());
					 /*QueryDomain<SysRoleFunction> queryDomain = new QueryDomain<SysRoleFunction>();
					 queryDomain.setParams(rf);
					 rf = sysRoleFunctionDao.getFirstOne(queryDomain);*/
					 rf = sysRoleFunctionDao.getOne(rf);
					 if (rf != null) {
						 sysRoleFunctionDao.deleteById(rf.getId());
					 }
				 }
			}
		}
		return 0;
	}

	@Override
	public List<SysRole> queryListByUserId(Integer userId) {
		List<SysRole> list = sysRoleDao.getbyUserId(userId);
		return list;
	}

	@Override
	public int saveRoleAndUser(UserAdminVo  user) {
		if (user != null) {
			SysRole deleteParam = new SysRole();
			deleteParam.setUserId(user.getId());
			if (StringUtils.isNotBlank(user.getRoleIds())) {
				Iterator<String> it = Splitter.on(",").trimResults().split(user.getRoleIds()).iterator();
				while(it.hasNext()) {  
					SysRoleUser ur = new SysRoleUser();
					ur.setRoleId(new Integer(it.next()));
					ur.setUserId(user.getId());
					sysRoleUserDao.insert(ur);
				}
			}
		}
		return 0;
	}

	@Override
	public void updateRoleAndMenu() {
		// 清除所有关系
		sysRoleMenuDao.deleteAll();
		//List<SysRole> roles = sysRoleDao.getBy(null);
		//List<SysMenu> menus = sysMenuDao.getAll();
		List<SysRole> roles = sysRoleDao.queryList(null);
		List<SysMenuVo> menus = sysMenuDao.getAll();
		List<SysRole> rs = new ArrayList<SysRole>(1);
		for(SysMenuVo m : menus) {
			if(m.getType().intValue() == SysMenuTypeDictEnum.ROOT.getCode() 
					|| m.getStatus().intValue() == SysMenuStatusDictEnum.DISABLE.getCode()) { // 菜单是目录 或者 状态禁用
				continue;
			}
			for(SysRole r : roles) {
				if (!r.getName().equals(SysConst.SYS_ROLE_ADMIN_NAME)) { // 总管理员不用
					rs.add(r);
					if(checkUrl(rs, m.getUrl())) {
						saveMenuCache(r,m);
					}
					rs.clear();
				}
			}
		}
		
	}
	
	/**
	 * 检查是否已经插入记录
	 * @param rm
	 * @return 有返回true,没有返回false
	 */
	public boolean checkHasRoleFunc(SysRoleFunction rf) {
		if (rf != null && rf.getFunctionId() != null && rf.getRoleId() != null) {
			/*QueryDomain<SysRoleFunction> queryDomain = new QueryDomain<SysRoleFunctionDomain>();
			queryDomain.setParams(rf);*/
			int value = sysRoleFunctionDao.queryCount(rf);
			if (value > 0) {
				return true;
			} else {
				return false;
			}
		}
		return true;
	}

	@Override
	public boolean checkUrl(UserAdmin userAdmin, String url) {
		List<SysRole> roles = sysRoleDao.getbyUserId(userAdmin.getId());
		return checkUrl(roles,url);
	}
	
	/**
	 * 检查菜单的url与功能的正则表达式
	 * @param roles
	 * @param url
	 * @return
	 */
	private boolean checkUrl(List<SysRole> roles, String url) {
		
		if(roles==null || roles.isEmpty() || StringUtils.isBlank(url)) {
			return false;
		}
		Map<String,Pattern> patternMap=new HashMap<String,Pattern>(200);
		
		//QueryDomain<SysRole> queryDomain = new QueryDomain<SysRole>();
		SysRole roleAdmin = new SysRole();
		roleAdmin.setName(SysConst.SYS_ROLE_ADMIN_NAME);
		roleAdmin.setStatus(SysRoleStatusDictEnum.ENABLE.getCode());
		//queryDomain.setParams(roleAdmin);
		//roleAdmin = sysRoleDao.getFirstOne(queryDomain);
		roleAdmin = sysRoleDao.getOne(roleAdmin);
		//roles.contains(roleAdmin)
		if(roleAdmin != null) {
			for(SysRole sysRole : roles){
				if(sysRole.getName().equals(SysConst.SYS_ROLE_ADMIN_NAME)){
					return true;		//如果有总管理员角色
				}
			}
		}
		// 查询角色拥有的功能
		SysFunctionQuery sysFunctionQuery = new SysFunctionQuery();
		sysFunctionQuery.setRoleIdList(new ArrayList<Integer>());
		for (SysRole r : roles) {
			sysFunctionQuery.getRoleIdList().add(r.getId());
		}
		List<SysFunctionVo> functions = sysFunctionDao.getByRoleId(sysFunctionQuery);
		
		for(SysFunction f : functions) {
			if(StringUtils.isBlank(f.getUrl())) {
				continue;
			}
			Pattern p = patternMap.get(f.getUrl());
			if(p==null) {
				p = Pattern.compile(f.getUrl());
				patternMap.put(f.getUrl(), p);
			}
			if(p.matcher(url).matches()) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 添加角色与菜单的缓存关联
	 * @param role
	 * @param menu
	 */
	private void saveMenuCache(SysRole role,SysMenu menu) {
		//如果未缓存,那么加入一条缓存记录
		if(!checkHasRoleMenu(role,menu)) { 
			SysRoleMenu sysRoleMenuDomain = new SysRoleMenu();
			sysRoleMenuDomain.setMenuId(menu.getMenuId());
			sysRoleMenuDomain.setRoleId(role.getId());
			sysRoleMenuDao.insert(sysRoleMenuDomain);
		}
		//递归缓存父菜单
		if(menu.getParentId()!=null) {
			SysMenuVo parent = sysMenuDao.getByMenuId(menu.getParentId());
			saveMenuCache(role, parent);
		}
	}
	
	/**
	 * 检查是否已经插入记录
	 * @param rm
	 * @return 有返回true,没有返回false
	 */
	public boolean checkHasRoleMenu(SysRole role,SysMenu menu) {
		SysRoleMenu sysRoleMenu = new SysRoleMenu();
		sysRoleMenu.setMenuId(menu.getMenuId());
		sysRoleMenu.setRoleId(role.getId());
		/*QueryDomain<SysRoleMenuDomain> queryDomain = new QueryDomain<SysRoleMenuDomain>();
		queryDomain.setParams(sysRoleMenuDomain);*/
		int value = sysRoleMenuDao.queryCount(sysRoleMenu);
		if (value > 0) {
			return true;
		} else {
			return false;
		}
	}
}